// 记录promise的三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

/**
 * 运行一个为队列任务
 * 把传递的函数放入到微队列
 * @param {Function} callback
 */
function runMicroTask(callback) {
  // 比较粗糙的写法
  // setTimeout(callback,0)

  // node环境中的微队列
  if (process && process.nextTick) {
    process.nextTick(callback);
  }
}

function isPromise(obj) {
  return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}

class MyPromise {
  /**
   *创建一个promise
   * @param {Function} executor 任务执行器 立即执行
   */
  constructor(executor) {
    this._state = PENDING;
    this._value = undefined;
    this._handlers = []; // 处理函数形成的队列
    try {
      executor(this._resolve.bind(this), this._reject.bind(this));
    } catch (error) {
      this._reject(error);
    }
  }
  /**
   * 想处理队列添加一个函数
   * @param {Function} executor  添加的函数
   * @param {String} state 该函数什么状态下执行
   * @param {Function} resove 让then函数返回的promise成功
   * @param {Function} reject 让then函数返回的promise失败
   */
  _pushHandler(executor, state, resolve, reject) {
    this._handlers.push({
      executor,
      state,
      resolve,
      reject,
    });
  }

  /**
   * 根据情况 执行队列
   * @returns
   */
  _runHandlers() {
    if (this._state === PENDING) {
      // 目前任务仍在挂起
      return;
    }
    // for (const handler of this._handlers) {
    //   this._runOneHandler(handler);
    //   this._handlers.shift()
    // }

    while (this._handlers[0]) {
      const handler = this._handlers[0];
      this._runOneHandler(handler);
      this._handlers.shift();
    }
  }

  /**
   * 处理一个handler
   * @param {Object} handler
   */
  _runOneHandler({ state, executor, resolve, reject }) {
    runMicroTask(() => {
      //this._state的状态和handler的状态不一致 不执行
      if (this._state !== state) return;
      // handler的executor 不是函数
      if (typeof executor !== "function") {
        //转态穿透
        this._state === FULFILLED ? resolve(this._value) : reject(this._value);
        return;
      }

      try {
        const result = executor(this._value);
        if (isPromise(result)) {
          result.then(resolve, reject);
        } else {
          resolve(result);
        }
      } catch (err) {
        reject(err);
      }
      // console.log(this._state);
      // console.log(handler);
    });
  }

  //
  // _runOneHandler(handler) {
  //   runMicroTask(() => {
  //     //this._state的状态和handler的状态不一致 不执行
  //     if (this._state !== handler.state) return;
  //     // handler的executor 不是函数
  //     if (typeof handler.executor !== "function") {
  //       //转态穿透
  //       this._state === FULFILLED
  //         ? handler.resolve(this._value)
  //         : handler.reject(this._value);
  //       return;
  //     }

  //     try {
  //       console.log(111);
  //       const result = handler.executor(this._value);
  //       console.log(111);
  //       if (isPromise(result)) {
  //         result.then(handler.resolve, handler.reject);
  //       } else {
  //         handler.resolve(result);
  //       }
  //     } catch (err) {
  //       handler.reject(err);
  //     }
  //     // console.log(this._state);
  //     // console.log(handler);
  //   });
  // }

  /**
   * Promise A+规范的then函数
   * @param {Function} onFulfilled
   * @param {Function} onRejected
   */
  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers(); // 直接调用, 因为可能已经已决
    });
  }

  /**
   * 更改任务状态
   * @param {string} newState 新状态
   * @param {*} value 新数据
   */
  _changeState(newState, value) {
    // 状态只能改变一次
    if (this._state !== PENDING) return;
    this._state = newState;
    this._value = value;

    // 转态变化后, 运行这个队列
    this._runHandlers();
  }

  /**
   * 标记当前任务完成
   * @param {any} data  任务完成的相关数据
   */
  _resolve(data) {
    // console.log("完成", data);
    // 改变状态和数据
    // this._state = FULFILLED;
    // this._value = data;

    // 简化一下
    this._changeState(FULFILLED, data);
  }

  /**
   * 标记当前任务失败
   * @param {any} reason  任务失败的相关数据
   */
  _reject(reason) {
    // console.log("失败", reason);
    // 改变状态和数据
    // this._state = REJECTED;
    // this._value = reason;

    //下面合并一下
    this._changeState(REJECTED, reason);
  }
}

// new Promise((resolve, reject) => {
//   resolve(123);
//   reject(234);
// }).then(
//   (res) => {
//     console.log(res);
//   },
//   (reason) => {
//     console.log(reason);
//   }
// );

const pro = new MyPromise((resolve, reject) => {
  resolve(1);
});
pro.then(
  function (res) {
    console.log(this);
  },
  () => {}
);

// console.log(pro);
